<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js light">
    <head>
        <!-- Book generated using mdBook -->
        <meta charset="UTF-8">
        <title>MEMORY_ALIGNMENT_ISSUE</title>
        
        


        <!-- Custom HTML head -->
        


        <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="theme-color" content="#ffffff" />

        
        <link rel="icon" href="../favicon.svg">
        
        
        <link rel="shortcut icon" href="../favicon.png">
        
        <link rel="stylesheet" href="../css/variables.css">
        <link rel="stylesheet" href="../css/general.css">
        <link rel="stylesheet" href="../css/chrome.css">
        
        <link rel="stylesheet" href="../css/print.css" media="print">
        

        <!-- Fonts -->
        <link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
        
        <link rel="stylesheet" href="../fonts/fonts.css">
        

        <!-- Highlight.js Stylesheets -->
        <link rel="stylesheet" href="../highlight.css">
        <link rel="stylesheet" href="../tomorrow-night.css">
        <link rel="stylesheet" href="../ayu-highlight.css">

        <!-- Custom theme stylesheets -->
        

        
    </head>
    <body>
        <!-- Provide site root to javascript -->
        <script type="text/javascript">
            var path_to_root = "../";
            var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
        </script>

        <!-- Work around some values being stored in localStorage wrapped in quotes -->
        <script type="text/javascript">
            try {
                var theme = localStorage.getItem('mdbook-theme');
                var sidebar = localStorage.getItem('mdbook-sidebar');

                if (theme.startsWith('"') && theme.endsWith('"')) {
                    localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
                }

                if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
                    localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
                }
            } catch (e) { }
        </script>

        <!-- Set the theme before any content is loaded, prevents flash -->
        <script type="text/javascript">
            var theme;
            try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
            if (theme === null || theme === undefined) { theme = default_theme; }
            var html = document.querySelector('html');
            html.classList.remove('no-js')
            html.classList.remove('light')
            html.classList.add(theme);
            html.classList.add('js');
        </script>

        <!-- Hide / unhide sidebar before it is displayed -->
        <script type="text/javascript">
            var html = document.querySelector('html');
            var sidebar = 'hidden';
            if (document.body.clientWidth >= 1080) {
                try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
                sidebar = sidebar || 'visible';
            }
            html.classList.remove('sidebar-visible');
            html.classList.add("sidebar-" + sidebar);
        </script>

        <nav id="sidebar" class="sidebar" aria-label="Table of contents">
            <div class="sidebar-scrollbox">
                <ol class="chapter"><li class="chapter-item expanded affix "><a href="../目录.html">目录</a></li><li class="chapter-item expanded "><a href="../如何阅读代码.html"><strong aria-hidden="true">1.</strong> 如何阅读代码</a></li><li class="chapter-item expanded "><a href="../应该知道的Linux技巧.html"><strong aria-hidden="true">2.</strong> 应该知道的Linux技巧</a></li><li class="chapter-item expanded "><a href="../bash/index.html"><strong aria-hidden="true">3.</strong> bash</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../bash/8个实用而有趣Bash命令提示行.html"><strong aria-hidden="true">3.1.</strong> 8个实用而有趣Bash命令提示行</a></li><li class="chapter-item expanded "><a href="../bash/Jobs.html"><strong aria-hidden="true">3.2.</strong> Jobs</a></li><li class="chapter-item expanded "><a href="../bash/ShellScript语法一.html"><strong aria-hidden="true">3.3.</strong> ShellScript语法一</a></li><li class="chapter-item expanded "><a href="../bash/ShellScript语法二.html"><strong aria-hidden="true">3.4.</strong> ShellScript语法二</a></li><li class="chapter-item expanded "><a href="../bash/argument_parameter_option.html"><strong aria-hidden="true">3.5.</strong> argument_parameter_option</a></li><li class="chapter-item expanded "><a href="../bash/如何调试bash脚本.html"><strong aria-hidden="true">3.6.</strong> 如何调试bash脚本</a></li><li class="chapter-item expanded "><a href="../bash/cheat_sheet/index.html"><strong aria-hidden="true">3.7.</strong> cheat_sheet</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../bash/cheat_sheet/sh.html"><strong aria-hidden="true">3.7.1.</strong> sh</a></li></ol></li></ol></li><li class="chapter-item expanded "><a href="../cmd/index.html"><strong aria-hidden="true">4.</strong> cmd</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../cmd/awk.html"><strong aria-hidden="true">4.1.</strong> awk</a></li><li class="chapter-item expanded "><a href="../cmd/nm.html"><strong aria-hidden="true">4.2.</strong> nm</a></li><li class="chapter-item expanded "><a href="../cmd/strace_ltrace.html"><strong aria-hidden="true">4.3.</strong> strace_ltrace</a></li><li class="chapter-item expanded "><a href="../cmd/tcpdump.html"><strong aria-hidden="true">4.4.</strong> tcpdump</a></li><li class="chapter-item expanded "><a href="../cmd/cheat_sheet/index.html"><strong aria-hidden="true">4.5.</strong> cheat_sheet</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../cmd/cheat_sheet/awk.html"><strong aria-hidden="true">4.5.1.</strong> awk</a></li><li class="chapter-item expanded "><a href="../cmd/cheat_sheet/tcpdump.html"><strong aria-hidden="true">4.5.2.</strong> tcpdump</a></li></ol></li></ol></li><li class="chapter-item expanded "><a href="../fileSystem/index.html"><strong aria-hidden="true">5.</strong> fileSystem</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../fileSystem/文件系统.html"><strong aria-hidden="true">5.1.</strong> 文件系统</a></li><li class="chapter-item expanded "><a href="../fileSystem/proc/index.html"><strong aria-hidden="true">5.2.</strong> proc</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../fileSystem/proc/[pid]_fd_socket.html"><strong aria-hidden="true">5.2.1.</strong> [pid]_fd_socket</a></li><li class="chapter-item expanded "><a href="../fileSystem/proc/[pid]_status.html"><strong aria-hidden="true">5.2.2.</strong> [pid]_status</a></li><li class="chapter-item expanded "><a href="../fileSystem/proc/net.html"><strong aria-hidden="true">5.2.3.</strong> net</a></li><li class="chapter-item expanded "><a href="../fileSystem/proc/proc浅谈.html"><strong aria-hidden="true">5.2.4.</strong> proc浅谈</a></li></ol></li></ol></li><li class="chapter-item expanded "><a href="../gcc_gdb/index.html"><strong aria-hidden="true">6.</strong> gcc_gdb</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../gcc_gdb/gdb的基本使用.html"><strong aria-hidden="true">6.1.</strong> gdb的基本使用</a></li></ol></li><li class="chapter-item expanded "><a href="../git/index.html"><strong aria-hidden="true">7.</strong> git</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../git/1_git基本要点.html"><strong aria-hidden="true">7.1.</strong> 1_git基本要点</a></li><li class="chapter-item expanded "><a href="../git/2_git配置.html"><strong aria-hidden="true">7.2.</strong> 2_git配置</a></li><li class="chapter-item expanded "><a href="../git/4_git本地操作.html"><strong aria-hidden="true">7.3.</strong> 4_git本地操作</a></li><li class="chapter-item expanded "><a href="../git/5_gitignore.html"><strong aria-hidden="true">7.4.</strong> 5_gitignore</a></li><li class="chapter-item expanded "><a href="../git/6_git分支操作.html"><strong aria-hidden="true">7.5.</strong> 6_git分支操作</a></li><li class="chapter-item expanded "><a href="../git/7_git远程仓库.html"><strong aria-hidden="true">7.6.</strong> 7_git远程仓库</a></li><li class="chapter-item expanded "><a href="../git/8_git通信协议.html"><strong aria-hidden="true">7.7.</strong> 8_git通信协议</a></li><li class="chapter-item expanded "><a href="../git/9_git服务器搭建.html"><strong aria-hidden="true">7.8.</strong> 9_git服务器搭建</a></li><li class="chapter-item expanded "><a href="../git/diff输出格式.html"><strong aria-hidden="true">7.9.</strong> diff输出格式</a></li><li class="chapter-item expanded "><a href="../git/git使用小技巧.html"><strong aria-hidden="true">7.10.</strong> git使用小技巧</a></li><li class="chapter-item expanded "><a href="../git/git分支.html"><strong aria-hidden="true">7.11.</strong> git分支</a></li><li class="chapter-item expanded "><a href="../git/git提供的工具.html"><strong aria-hidden="true">7.12.</strong> git提供的工具</a></li><li class="chapter-item expanded "><a href="../git/git衍合.html"><strong aria-hidden="true">7.13.</strong> git衍合</a></li><li class="chapter-item expanded "><a href="../git/extend/index.html"><strong aria-hidden="true">7.14.</strong> extend</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../git/extend/git_http请求分析.html"><strong aria-hidden="true">7.14.1.</strong> git_http请求分析</a></li></ol></li></ol></li><li class="chapter-item expanded "><a href="../gpg/index.html"><strong aria-hidden="true">8.</strong> gpg</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../gpg/gpg的简单使用.html"><strong aria-hidden="true">8.1.</strong> gpg的简单使用</a></li></ol></li><li class="chapter-item expanded "><a href="../language/index.html"><strong aria-hidden="true">9.</strong> language</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../language/empty.html"><strong aria-hidden="true">9.1.</strong> empty</a></li><li class="chapter-item expanded "><a href="../language/c_plus_plus/index.html"><strong aria-hidden="true">9.2.</strong> c_plus_plus</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../language/c_plus_plus/4个类型转换关键字.html"><strong aria-hidden="true">9.2.1.</strong> 4个类型转换关键字</a></li><li class="chapter-item expanded "><a href="../language/c_plus_plus/RTTI.html"><strong aria-hidden="true">9.2.2.</strong> RTTI</a></li><li class="chapter-item expanded "><a href="../language/c_plus_plus/const.html"><strong aria-hidden="true">9.2.3.</strong> const</a></li><li class="chapter-item expanded "><a href="../language/c_plus_plus/内存对齐.html"><strong aria-hidden="true">9.2.4.</strong> 内存对齐</a></li><li class="chapter-item expanded "><a href="../language/c_plus_plus/拷贝赋值.html"><strong aria-hidden="true">9.2.5.</strong> 拷贝赋值</a></li><li class="chapter-item expanded "><a href="../language/c_plus_plus/指针.html"><strong aria-hidden="true">9.2.6.</strong> 指针</a></li><li class="chapter-item expanded "><a href="../language/c_plus_plus/构造析构.html"><strong aria-hidden="true">9.2.7.</strong> 构造析构</a></li><li class="chapter-item expanded "><a href="../language/c_plus_plus/私有不可访问吗.html"><strong aria-hidden="true">9.2.8.</strong> 私有不可访问吗</a></li><li class="chapter-item expanded "><a href="../language/c_plus_plus/继承.html"><strong aria-hidden="true">9.2.9.</strong> 继承</a></li><li class="chapter-item expanded "><a href="../language/c_plus_plus/虚函数.html"><strong aria-hidden="true">9.2.10.</strong> 虚函数</a></li><li class="chapter-item expanded "><a href="../language/c_plus_plus/静态库的链接.html"><strong aria-hidden="true">9.2.11.</strong> 静态库的链接</a></li></ol></li><li class="chapter-item expanded "><a href="../language/python/index.html"><strong aria-hidden="true">9.3.</strong> python</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../language/python/optparse的简单使用.html"><strong aria-hidden="true">9.3.1.</strong> optparse的简单使用</a></li></ol></li></ol></li><li class="chapter-item expanded "><a href="../linux编程/index.html"><strong aria-hidden="true">10.</strong> linux编程</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../linux编程/常用开发工具.html"><strong aria-hidden="true">10.1.</strong> 常用开发工具</a></li><li class="chapter-item expanded "><a href="../linux编程/线程.html"><strong aria-hidden="true">10.2.</strong> 线程</a></li><li class="chapter-item expanded "><a href="../linux编程/进程.html"><strong aria-hidden="true">10.3.</strong> 进程</a></li><li class="chapter-item expanded "><a href="../linux编程/fs/index.html"><strong aria-hidden="true">10.4.</strong> fs</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../linux编程/fs/dir.html"><strong aria-hidden="true">10.4.1.</strong> dir</a></li><li class="chapter-item expanded "><a href="../linux编程/fs/file.html"><strong aria-hidden="true">10.4.2.</strong> file</a></li><li class="chapter-item expanded "><a href="../linux编程/fs/getcwd_chdir.html"><strong aria-hidden="true">10.4.3.</strong> getcwd_chdir</a></li><li class="chapter-item expanded "><a href="../linux编程/fs/stat.html"><strong aria-hidden="true">10.4.4.</strong> stat</a></li></ol></li></ol></li><li class="chapter-item expanded "><a href="../make/index.html"><strong aria-hidden="true">11.</strong> make</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../make/Makefile.html"><strong aria-hidden="true">11.1.</strong> Makefile</a></li></ol></li><li class="chapter-item expanded "><a href="../other/index.html"><strong aria-hidden="true">12.</strong> other</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../other/linux设置代理.html"><strong aria-hidden="true">12.1.</strong> linux设置代理</a></li><li class="chapter-item expanded "><a href="../other/负数的补码怎么得到.html"><strong aria-hidden="true">12.2.</strong> 负数的补码怎么得到</a></li><li class="chapter-item expanded "><a href="../other/缓存/index.html"><strong aria-hidden="true">12.3.</strong> 缓存</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../other/缓存/缓存穿透_击穿_雪崩.html"><strong aria-hidden="true">12.3.1.</strong> 缓存穿透_击穿_雪崩</a></li></ol></li></ol></li><li class="chapter-item expanded "><a href="../reference/index.html"><strong aria-hidden="true">13.</strong> reference</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../reference/MEMORY_ALIGNMENT_ISSUE.html" class="active"><strong aria-hidden="true">13.1.</strong> MEMORY_ALIGNMENT_ISSUE</a></li></ol></li><li class="chapter-item expanded "><a href="../small_program/index.html"><strong aria-hidden="true">14.</strong> small_program</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../small_program/程序模块.html"><strong aria-hidden="true">14.1.</strong> 程序模块</a></li></ol></li><li class="chapter-item expanded "><a href="../ssh/index.html"><strong aria-hidden="true">15.</strong> ssh</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../ssh/ssh的高级使用方式.html"><strong aria-hidden="true">15.1.</strong> ssh的高级使用方式</a></li><li class="chapter-item expanded "><a href="../ssh/ssh私钥登录.html"><strong aria-hidden="true">15.2.</strong> ssh私钥登录</a></li></ol></li><li class="chapter-item expanded "><a href="../ubuntu/index.html"><strong aria-hidden="true">16.</strong> ubuntu</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../ubuntu/启动器文件.html"><strong aria-hidden="true">16.1.</strong> 启动器文件</a></li></ol></li><li class="chapter-item expanded "><a href="../x/index.html"><strong aria-hidden="true">17.</strong> x</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../x/Linux下的X是什么.html"><strong aria-hidden="true">17.1.</strong> Linux下的X是什么</a></li><li class="chapter-item expanded "><a href="../x/Win10安装VCXSRV.html"><strong aria-hidden="true">17.2.</strong> Win10安装VCXSRV</a></li><li class="chapter-item expanded "><a href="../x/XApplication配置.html"><strong aria-hidden="true">17.3.</strong> XApplication配置</a></li><li class="chapter-item expanded "><a href="../x/startx与xinit.html"><strong aria-hidden="true">17.4.</strong> startx与xinit</a></li></ol></li><li class="chapter-item expanded "><a href="../技术名词/index.html"><strong aria-hidden="true">18.</strong> 技术名词</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../技术名词/cheat_sheet.html"><strong aria-hidden="true">18.1.</strong> cheat_sheet</a></li></ol></li><li class="chapter-item expanded "><a href="../网络/index.html"><strong aria-hidden="true">19.</strong> 网络</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../网络/linux网络.html"><strong aria-hidden="true">19.1.</strong> linux网络</a></li><li class="chapter-item expanded "><a href="../网络/标准的简单网络服务.html"><strong aria-hidden="true">19.2.</strong> 标准的简单网络服务</a></li><li class="chapter-item expanded "><a href="../网络/计算机网络.html"><strong aria-hidden="true">19.3.</strong> 计算机网络</a></li><li class="chapter-item expanded "><a href="../网络/tcp/index.html"><strong aria-hidden="true">19.4.</strong> tcp</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../网络/tcp/tcpKeepAlive与复位报文.html"><strong aria-hidden="true">19.4.1.</strong> tcpKeepAlive与复位报文</a></li><li class="chapter-item expanded "><a href="../网络/tcp/tcpKeepAlive与应用层keepAlive.html"><strong aria-hidden="true">19.4.2.</strong> tcpKeepAlive与应用层keepAlive</a></li><li class="chapter-item expanded "><a href="../网络/tcp/tcp简介.html"><strong aria-hidden="true">19.4.3.</strong> tcp简介</a></li></ol></li></ol></li><li class="chapter-item expanded "><a href="../装机高手/index.html"><strong aria-hidden="true">20.</strong> 装机高手</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../装机高手/empty.html"><strong aria-hidden="true">20.1.</strong> empty</a></li></ol></li></ol>
            </div>
            <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
        </nav>

        <div id="page-wrapper" class="page-wrapper">

            <div class="page">
                
                <div id="menu-bar-hover-placeholder"></div>
                <div id="menu-bar" class="menu-bar sticky bordered">
                    <div class="left-buttons">
                        <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
                            <i class="fa fa-bars"></i>
                        </button>
                        <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
                            <i class="fa fa-paint-brush"></i>
                        </button>
                        <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
                            <li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
                        </ul>
                        
                        <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
                            <i class="fa fa-search"></i>
                        </button>
                        
                    </div>

                    <h1 class="menu-title"></h1>

                    <div class="right-buttons">
                        
                        <a href="../print.html" title="Print this book" aria-label="Print this book">
                            <i id="print-button" class="fa fa-print"></i>
                        </a>
                        
                        
                    </div>
                </div>

                
                <div id="search-wrapper" class="hidden">
                    <form id="searchbar-outer" class="searchbar-outer">
                        <input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
                    </form>
                    <div id="searchresults-outer" class="searchresults-outer hidden">
                        <div id="searchresults-header" class="searchresults-header"></div>
                        <ul id="searchresults">
                        </ul>
                    </div>
                </div>
                

                <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
                <script type="text/javascript">
                    document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
                    document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
                    Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
                        link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
                    });
                </script>

                <div id="content" class="content">
                    <main>
                        <h1 id="memory-alignment-issue"><a class="header" href="#memory-alignment-issue">MEMORY ALIGNMENT ISSUE</a></h1>
<p><a href="http://junyelee.blogspot.com/2019/01/memory-alignment-issue.html">源地址</a></p>
<h2 id="alignment-fundamentals"><a class="header" href="#alignment-fundamentals">Alignment fundamentals</a></h2>
<p>When a computer reads from or writes to a memory address, it will do this in word sized chunks (for example, 4 byte (32-bit) chunks on the MPC8360). We'll call the size in which a processor accesses memory its memory access granularity.</p>
<p>Data alignment means putting the data at a memory offset equal to processor's memory access granularity, which increases the system's performance due to the way the CPU handles memory. Most CPUs can access only memory aligned addresses.</p>
<p>To illustrate how a processor's memory access granularity affects memory access, let's compare the following tasks:
read 4 bytes from address 0 into the processor's register
read 4 bytes from address 1 into the same register
It would happen on a processor with 4-byte memory access granularity,</p>
<p>read 4 bytes from the aligned address 0 needs single read instruction
read 4 bytes from the un-aligned address 1 into the same register needs 2 read instructions</p>
<p>The following show an example of some memory addresses and their alignment on different architectures.</p>
<h2 id="linux-unaligned-memory-accesses"><a class="header" href="#linux-unaligned-memory-accesses">Linux: UNALIGNED MEMORY ACCESSES</a></h2>
<p>Linux runs on a wide variety of architectures which have varying behavior when it comes to memory access.</p>
<p>The definition of an unaligned access</p>
<p>Unaligned memory accesses occur when you try to read N bytes of data starting from an address that is not evenly divisible by N (i.e. addr % N != 0).
For example, reading 4 bytes of data from address 0x10004 is fine, but reading 4 bytes of data from address 0x10005 would be an unaligned memory access.
The context here is at the machine code level: certain instructions read or write a number of bytes to or from memory (e.g. movb, movw, movl in x86 assembly).</p>
<p>Natural alignment</p>
<p>When accessing N bytes of memory, the base memory address must be evenly divisible by N, i.e.</p>
<pre><code> addr % N == 0
</code></pre>
<p>Why unaligned access is bad</p>
<p>a summary of the common scenarios is presented below:
Some architectures are able to perform unaligned memory accesses transparently, but there is usually a significant performance cost.
Some architectures raise processor exceptions when unaligned accesses happen. The exception handler is able to correct the unaligned access, at significant cost to performance.
Some architectures raise processor exceptions when unaligned accesses happen, but the exceptions do not contain enough information for the unaligned access to be corrected.
Some architectures are not capable of unaligned memory access, but will silently perform a different memory access to the one that was requested, resulting in a subtle code bug that is hard to detect!
It should be obvious from the above that if your code causes unaligned memory accesses to happen, your code will not work correctly on certain platforms and will cause performance problems on others.</p>
<p>Code that does not cause unaligned access
For example, take the following structure::</p>
<pre><code> struct foo {
  u16 field1;
  u32 field2;
  u8 field3;
 };
</code></pre>
<p>You'd be expecting field2 to be located at offset 2 bytes into the structure, i.e. address 0x10002, but that address is not evenly divisible by 4.
Fortunately, the compiler understands the alignment constraints, so in the above case it would insert 2 bytes of padding in between field1 and field2.
Therefore, for standard structure types you can always rely on the compiler to pad structures so that accesses to fields are suitably aligned.</p>
<p>Similarly, you can also rely on the compiler to align variables and function parameters to a naturally aligned scheme, based on the size of the type of the variable.</p>
<p>At this point, it should be clear that accessing a single byte (u8 or char) will never cause an unaligned access, because all memory addresses are evenly divisible by one.</p>
<p>The optimal layout of the above example is::</p>
<pre><code> struct foo {
  u32 field2;
  u16 field1;
  u8 field3;
 };
</code></pre>
<p>For a natural alignment scheme, the compiler would only have to add a single byte of padding at the end of the structure.
The compiler is aware of the alignment constraints and will generate extra instructions to perform the memory access in a way that does not cause unaligned access.</p>
<p>Code that causes unaligned access</p>
<p>The following function taken from include/linux/etherdevice.h is an optimized routine to compare two ethernet MAC addresses( 48-bits, 6 bytes ) for equality::</p>
<pre><code>  bool ether_addr_equal(const u8 *addr1, const u8 *addr2)
  {
  #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
 u32 fold = ((*(const u32 *)addr1) ^ (*(const u32 *)addr2)) |
     ((*(const u16 *)(addr1 + 4)) ^ (*(const u16 *)(addr2 + 4)));

 return fold == 0;
  #else
 const u16 *a = (const u16 *)addr1;
 const u16 *b = (const u16 *)addr2;
 return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) == 0;
  #endif
  }
</code></pre>
<p>When CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set, the hardware isn't able to access memory on arbitrary boundaries, the reference to a[0] causes 2 bytes (16 bits) to be read from memory starting at address addr1. This is understood to only work normally on 16-bit-aligned addresses.</p>
<p>Here is another example of some code that could cause unaligned accesses::</p>
<pre><code> void myfunc(u8 *data, u32 value)
 {
  [...]
  *((u32 *) data) = cpu_to_le32(value);
  [...]
 }
</code></pre>
<p>This code will cause unaligned accesses every time the data pointer parameter points to an address that is not evenly divisible by 4.</p>
<h3 id="avoiding-unaligned-accesses"><a class="header" href="#avoiding-unaligned-accesses">Avoiding unaligned accesses</a></h3>
<p>The easiest way to avoid unaligned access is to use the get_unaligned() and put_unaligned() macros provided by the &lt;asm/unaligned.h&gt;l header file. &quot;unaligned.h&quot; is an architecture-dependent file.
read from an address</p>
<p>u32 value = get_unaligned((u32 *) mem_addr);
write to an address</p>
<p>put_unaligned(value, (u32 *) mem_addr);
These macros work for memory accesses of any length (not just 32 bits as in the examples above). Be aware that when compared to standard access of aligned memory, using these macros to access unaligned memory can be costly in terms of performance.</p>
<p>How does the ARM Compiler support unaligned accesses?</p>
<p>Older ARM processors require data load and stores to be to/from architecturally aligned addresses. This means:</p>
<p>LDRB/STRB          - address must be byte aligned
LDRH/STRH          - address must be 2-byte aligned 
LDR/STR            - address must be 4-byte aligned</p>
<p>Load/store instructions that act on multiple registers, for example LDM, are considered as working with multiple word quantities, so these instructions also require 4-byte aligned addresses. An unaligned load is one where the address does not match the architectural alignment.</p>
<p>On older processors, such as ARM9 family based processors, an unaligned load had to be synthesized in software. Typically by doing a series of small accesses, and combining the results.</p>
<p>The ARMv6 architecture introduced the first hardware support for unaligned accesses. ARM11 and Cortex-A/R processors can deal with unaligned accesses in hardware, removing the need for software routines.</p>
<p>Support for unaligned accesses is limited to a sub-set of load/store instructions:</p>
<p>LDRB/LDRSB/STRB
LDRH/LDRSH/STRH
LDR/STR
Instructions which do NOT support unaligned accesses include:</p>
<p>LDM/STM
LDRD/STRD
Further, unaligned accesses are only allowed to regions marked as Normal memory type, and unaligned access support must be enabled by setting the SCTLR.A bit in the system control coprocessor. Attempts to perform unaligned accesses when not allowed will cause an alignment fault (data abort).</p>
<p>How hardware supports unaligned accesses</p>
<p>In many cases a processor cannot generate an unaligned access on its interfaces to the memory system. This applies to caches, TCMs and the system bus. In these situations, the processor will generate a series of accesses, to implement the unaligned access. This is similar to the software routines used for previous processors.</p>
<p>For example:</p>
<pre><code>    LDR r0, [0x8001]
</code></pre>
<p>Most modern ARM processors have 64-bit or 128-bit interfaces. In the above example a processor would typically read the 64-bit or 128-bit block contains bytes 0x8001, 0x8002, 0x8003 and 0x8004. Discarding the other bytes.</p>
<p>Another example:</p>
<pre><code>    LDR r0, [0x81FC]
</code></pre>
<p>The four bytes of this load span both a 64-bit and 128-bit boundary. So with either interface width, the processor would have to perform two reads.</p>
<p>In both of these examples it is possible to see that unaligned accesses require more work by the hardware. While more efficient than the software routines required by previous processors, it is still less efficient than aligned accesses.</p>
<h3 id="pointer-alignment-in-c"><a class="header" href="#pointer-alignment-in-c">Pointer alignment in C</a></h3>
<p>When compiling C, variables are by default architecturally aligned. A global of type int (or uint32_t) will be 4-byte aligned in memory. Similarly, a pointer of type int* is expected to contain a 4-byte aligned address.</p>
<p>Where this is not the case (or may not be the case) the variable or pointer MUST be marked with the __packed keyword. This is a warning to the compiler that this variable, structure or pointer is potentially unaligned. Technically, it reduces the expected alignment of the pointer to 1-byte. It is possible to set the alignment of all pointers to 1 by using the compiler command line switch --pointer_alignment=1, it which case the compiler will treat all accesses through pointers as though they may be unaligned.</p>
<h3 id="compiler-assumptions"><a class="header" href="#compiler-assumptions">Compiler assumptions</a></h3>
<p>When compiling for a ARMv6 or ARMv7-A/R processor, the ARM Compiler will assume that it can use unaligned accesses.</p>
<p>The --no_unaligned_access flag tells the compiler not to knowingly generate unaligned accesses. What is the significance of knowingly?</p>
<p>As mentioned above, a pointer should contain an address with correct alignment for the type.</p>
<pre><code>uint32_t* requires 4-byte alignment
uint16_t* requires 2-byte alignment
uint8_t* requires 1-byte alignment
</code></pre>
<p>For structures, the alignment is that of the most aligned member.</p>
<p>The compiler will generate code on the assumption that a pointer is correctly aligned. It does not add code to perform run-time checks. A pointer may contain an incorrectly aligned address for a number of reasons. A common cause is casting:</p>
<pre><code>uint8_t tmp;
uint32_t* pMyPointer = (uint32_t*)(&amp;tmp);
</code></pre>
<p>This code takes the address of an uint8_t variable, then casts that address as a uint32_t pointer. The compiler will still assume that pMyPointer is correctly aligned for a uint32_t pointer. The compiler might then generate code that results in an unaligned access unknowingly.</p>
<p>This can be avoided using the __packed qualifier:</p>
<p>__packed uint32_t* pMyPointer = (__packed uint32_t*)(&amp;tmp);</p>
<h2 id="code-generation"><a class="header" href="#code-generation">Code Generation</a></h2>
<p>When unaligned accesses are permitted, the compiler will continue to use instructions that support unaligned accesses (for example LDR and STR) for accesses through __packed pointers. However it will not use instructions such as LDM which do not support unaligned accesses.</p>
<p>When unaligned accesses are not permitted, either because the code is being built for an ARMv4 or ARMv5 processor, or because --no_unaligned_access is specified, the compiler will access __packed data by a performing a number of aligned accesses. Usually, this is done by calling a library function such as __aeabi_uread4().</p>
<h2 id="device-memory"><a class="header" href="#device-memory">Device Memory</a></h2>
<p>Address regions that are used to access peripherals rather than memory should be marked as Device memory. Depending upon the processor, this may be configured in the Memory Protection Unit (MPU) or the Memory Management Unit (MMU). Unaligned accesses are not permitted to these regions even when unaligned access support is enabled. If an unaligned access is attempted, the processor will take an abort.</p>
<p>The compiler does not have any information on which address ranges are device memory, and it is therefore the responsibility of the person writing the code to ensure that accesses to devices are aligned. In practice, this usually is the case simply because peripheral registers are at aligned addresses. It is also usual to access peripheral registers through volatile variables or pointers, which restricts the compiler to accessing the data with the size of access specified where possible. For further information on the restrictions imposed on volatile types, please see section 7.1.5 of the Procedure Call Standard for the ARM Architecture.</p>
<p>It is also necessary to avoid using C library functions such as memcpy() to access Device memory, as there is no guarantee of the type of accesses these functions will use. If it is necessary to copy a buffer of memory to a Device memory, you should provide a suitable copying routine and call this instead of memcpy().</p>
<h2 id="performance"><a class="header" href="#performance">Performance</a></h2>
<p>If code frequently accesses unaligned data, there may be a performance advantage in enabling unaligned accesses. However, the extent of this advantage will be dependent on many factors. Even though this support allows a single instruction to access unaligned data, this will often require multiple bus accesses to occur. Therefore the bus transactions performed by an unaligned access may be similar to those performed by the multiple instructions used when unaligned access support is disabled. The code without unaligned access support will have to perform various shift and logical operations, but on a multi-issue processor the execution time of these may be hidden by executing them in parallel with the memory accesses. There will also be a function call overhead when functions such as __aeabi_uread4() are used, though the impact of these may be reduced by branch prediction.</p>

                    </main>

                    <nav class="nav-wrapper" aria-label="Page navigation">
                        <!-- Mobile navigation buttons -->
                        
                            <a rel="prev" href="../reference/index.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                                <i class="fa fa-angle-left"></i>
                            </a>
                        

                        
                            <a rel="next" href="../small_program/index.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                                <i class="fa fa-angle-right"></i>
                            </a>
                        

                        <div style="clear: both"></div>
                    </nav>
                </div>
            </div>

            <nav class="nav-wide-wrapper" aria-label="Page navigation">
                
                    <a rel="prev" href="../reference/index.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                        <i class="fa fa-angle-left"></i>
                    </a>
                

                
                    <a rel="next" href="../small_program/index.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                        <i class="fa fa-angle-right"></i>
                    </a>
                
            </nav>

        </div>

        
        <!-- Livereload script (if served using the cli tool) -->
        <script type="text/javascript">
            var socket = new WebSocket("ws://localhost:3000/__livereload");
            socket.onmessage = function (event) {
                if (event.data === "reload") {
                    socket.close();
                    location.reload();
                }
            };

            window.onbeforeunload = function() {
                socket.close();
            }
        </script>
        

        

        

        
        <script type="text/javascript">
            window.playground_copyable = true;
        </script>
        

        

        
        <script src="../elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="../mark.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="../searcher.js" type="text/javascript" charset="utf-8"></script>
        

        <script src="../clipboard.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="../highlight.js" type="text/javascript" charset="utf-8"></script>
        <script src="../book.js" type="text/javascript" charset="utf-8"></script>

        <!-- Custom JS scripts -->
        

        

    </body>
</html>
